home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1992 June: ROMin Holiday / ADC Developer CD (1992-06) (''ROMin Holiday'')_iso / Developer Connection - 06-1992.iso / Developer Essentials / DTS Sample Code / System 7.0 Samples / Kibitz / DoEvent.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-02-21  |  13.6 KB  |  564 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:        Kibitz
  5. ** File:        doevent.c
  6. ** Written by:  Eric Soldan
  7. **
  8. ** Copyright © 1990-1991 Apple Computer, Inc.
  9. ** All rights reserved.
  10. */
  11.  
  12.  
  13.  
  14. /*****************************************************************************/
  15.  
  16.  
  17.  
  18. #include "Kibitz.h"                /* Get the Kibitz includes/typedefs, etc.    */
  19. #include "KibitzCommon.h"        /* Get the stuff in common with rez.        */
  20. #include "Kibitz.protos"        /* Get the prototypes for Kibitz.            */
  21.  
  22. #ifndef __DESK__
  23. #include <Desk.h>
  24. #endif
  25.  
  26. #ifndef __DISKINIT__
  27. #include <DiskInit.h>
  28. #endif
  29.  
  30. #ifndef __ERRORS__
  31. #include <Errors.h>
  32. #endif
  33.  
  34. #ifndef __MENUS__
  35. #include <Menus.h>
  36. #endif
  37.  
  38. #ifndef __TEXTEDITCONTROL__
  39. #include <TextEditControl.h>
  40. #endif
  41.  
  42. #ifndef __TOOLUTILS__
  43. #include <ToolUtils.h>
  44. #endif
  45.  
  46. #ifndef __UTILITIES__
  47. #include <Utilities.h>
  48. #endif
  49.  
  50.  
  51.  
  52. /*****************************************************************************/
  53.  
  54.  
  55.  
  56. extern Cursor    *gCurrentCursor;
  57.  
  58.  
  59.  
  60. /*****************************************************************************/
  61. /*****************************************************************************/
  62.  
  63.  
  64.  
  65. /* Do the right thing for an event.  Determine what kind of event it is, and
  66. ** call the appropriate routines.
  67. */
  68.  
  69. #pragma segment Main
  70. void    DoEvent(EventRecord *event)
  71. {
  72.     short            part, err;
  73.     WindowPtr        window;
  74.     char            key;
  75.     Point            aPoint;
  76.     FileRecHndl        frHndl;
  77.     ControlHandle    ctl;
  78.     long            tick;
  79.     Rect            boardRct;
  80.  
  81.     switch(event->what) {
  82.  
  83.         case mouseDown:
  84.             gCurrentCursor = nil;
  85.                 /* No shortcuts when we recalculate the cursor region. */
  86.  
  87.             part = FindWindow(event->where, &window);
  88.             if (part != inContent) DoSetCursor(&qd.arrow);
  89.  
  90.             switch(part) {
  91.  
  92.                 case inContent:
  93.                     if (window != FrontWindow()) {
  94.                         SelectWindow(window);
  95.                         if (IsAppWindow(window)) {
  96.                             DoUpdate(window);
  97.                             boardRct = GlobalBoardRect(window);
  98.                             if (PtInRect(event->where, &boardRct))
  99.                                 DoEvent(event);
  100.                         }
  101.                                     /* Do first click if over board. */
  102.                     } else
  103.                         DoContentClick(window, event);
  104.                     break;
  105.  
  106.                 case inDrag:            
  107.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  108.                     break;        /* Pass screenBits.bounds to
  109.                                 ** get all gDevices. */
  110.  
  111.                 case inGoAway:
  112.                     if (TrackGoAway(window, event->where)) {
  113.                         CloseOneWindow(window, iClose);
  114.                     }
  115.                     break;
  116.  
  117.                 case inGrow:
  118.                     break;
  119.  
  120.                 case inMenuBar:        /* Process mouse menu command (if any). */
  121.                     AdjustMenus();
  122.                     DoMenuCommand(MenuSelect(event->where));
  123.                     break;
  124.  
  125.                 case inSysWindow:    /* Let the system handle the mouseDown. */
  126.                     SystemClick(event, window);
  127.                     break;
  128.  
  129.                 case inZoomIn:
  130.                 case inZoomOut:
  131.                     if (TrackBox(window, event->where, part))
  132.                         ZoomToWindowDevice(window, 0, 0, part, true);
  133.                     break;
  134.  
  135.             }
  136.             break;
  137.  
  138.         case activateEvt:
  139.             gCurrentCursor = nil;
  140.                 /* No shortcuts when we recalculate the cursor region. */
  141.  
  142.             DoActivate((WindowPtr)event->message,
  143.                        (event->modifiers & activeFlag));
  144.             break;
  145.  
  146.         case autoKey:
  147.         case keyDown:                    /* Check for menukey equivalents. */
  148.             key = event->message & charCodeMask;
  149.             if (event->modifiers & cmdKey) {        /* Command key down. */
  150.                 if (event->what == keyDown) {
  151.                     AdjustMenus();
  152.                         /* Enable/disable/check menu items properly. */
  153.                     DoMenuCommand(MenuKey(key));
  154.                 }
  155.             }
  156.             else {
  157.                 if (!IsAppWindow(window = FrontWindow())) break;
  158.                 frHndl = (FileRecHndl)GetWRefCon(window);
  159.                 if (key == 0x03) {
  160.                     ctl = (*frHndl)->doc.sendMessage;
  161.                     if (!(*ctl)->contrlHilite) {
  162.                         HiliteControl(ctl, 1);
  163.                         tick = TickCount();
  164.                         while (TickCount() < tick + 10);
  165.                         HiliteControl(ctl, 0);
  166.                         SendMssg(frHndl, kTextMssg);
  167.                     }
  168.                 }
  169.                 else {
  170.                     if (CTEKey(event)) {
  171.                         AdjustMenus();        /* Avoid unnecessary DoCursor() and speed */
  172.                         return;                /* up TextEdit entry. */
  173.                     }
  174.                 }
  175.             }
  176.             break;
  177.  
  178.         case diskEvt:
  179.             gCurrentCursor = nil;
  180.                 /* No shortcuts when we recalculate the cursor region. */
  181.  
  182.             if (HiWord(event->message) != noErr) {
  183.                 SetPt(&aPoint, kDILeft, kDITop);
  184.                 err = DIBadMount(aPoint, event->message);
  185.             }
  186.             break;        /* It is not a bad idea to at least call DIBadMount
  187.                         ** in response to a diskEvt, so that the user can
  188.                         ** format a floppy.
  189.                         */
  190.         case kHighLevelEvent:
  191.             gCurrentCursor = nil;
  192.                 /* No shortcuts when we recalculate the cursor region. */
  193.  
  194.             DoHighLevelEvent(event);
  195.             break;
  196.  
  197.         case kOSEvent:
  198.             gCurrentCursor = nil;
  199.                 /* No shortcuts when we recalculate the cursor region. */
  200.  
  201.             switch ((event->message >> 24) & 0x0FF) {
  202.                     /* Must logical and with 0x0FF to get only low byte. */
  203.                     /* High byte of message. */
  204.  
  205.                 case kMouseMovedMessage:
  206.                     break;
  207.  
  208.                 case kSuspendResumeMessage:
  209.                         /* Suspend/resume is also an activate/deactivate. */
  210.                     gInBackground = !(event->message & kResumeMask);
  211.                     DoActivate(FrontWindow(), !gInBackground);
  212.                     break;
  213.             }
  214.             break;
  215.  
  216.         case updateEvt:
  217.             DoUpdate((WindowPtr)event->message);
  218.             break;
  219.  
  220.     }
  221.  
  222.     DoCursor(false, 0);
  223.     AdjustMenus();
  224. }
  225.  
  226.  
  227.  
  228. /*****************************************************************************/
  229.  
  230.  
  231.  
  232. /* This is called when a window is activated or deactivated. */
  233.  
  234. #pragma segment Main
  235. void    DoActivate(WindowPtr window, Boolean becomingActive)
  236. {
  237.     FileRecHndl        frHndl;
  238.     short            hilite;
  239.     ControlHandle    ctl;
  240.  
  241.     NotifyCancel();
  242.  
  243.     if (IsAppWindow(window)) {
  244.  
  245.         frHndl = (FileRecHndl)GetWRefCon(window);
  246.  
  247.         SetPort(window);
  248.         SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  249.  
  250.         hilite = 0;
  251.         if (!becomingActive) hilite = 255;
  252.  
  253.         HiliteControl((*frHndl)->doc.gameSlider, hilite);
  254.         HiliteControl((*frHndl)->doc.resign, hilite);
  255.         HiliteControl((*frHndl)->doc.draw, hilite);
  256.  
  257.         if (!(*frHndl)->doc.twoPlayer) hilite = 255;
  258.  
  259.         HiliteControl(ctl = (*frHndl)->doc.sendMessage, hilite);
  260.         OutlineControl(ctl);
  261.         HiliteControl((*frHndl)->doc.beepOnMove, hilite);
  262.         HiliteControl((*frHndl)->doc.beepOnMssg, hilite);
  263.  
  264.         if (!SoundInputAvaliable()) hilite = 255;
  265.         HiliteControl((*frHndl)->doc.record, hilite);
  266.         if (!(*frHndl)->doc.sound) hilite = 255;
  267.         HiliteControl((*frHndl)->doc.sendSnd, hilite);
  268.  
  269.         if ((*frHndl)->doc.arrangeBoard) becomingActive = false;
  270.         CTEWindActivate(window, becomingActive);
  271.  
  272.         DoDrawControls(window, true);
  273.         SetOrigin(0, 0);
  274.     }
  275. }
  276.  
  277.  
  278.  
  279. /*****************************************************************************/
  280.  
  281.  
  282.  
  283. /* This is called when an update event is received for a window.  It calls
  284. ** ImageDocument to draw the contents of an application window.  As an
  285. ** effeciency measure that does not have to be followed, it calls the drawing
  286. ** routine only if the visRgn is non-empty.  This will handle situations where
  287. ** calculations for drawing or drawing itself is very time-consuming.
  288. */
  289.  
  290. #pragma segment Main
  291. void    DoUpdate(WindowPtr window)
  292. {
  293.     if (IsAppWindow(window)) {
  294.         BeginUpdate(window);                /* This sets up the visRgn. */
  295.         if (!EmptyRgn(window->visRgn)) {    /* Draw if updating needs doing. */
  296.             SetPort(window);
  297.             ImageDocument((FileRecHndl)GetWRefCon(window), false);
  298.         }
  299.         EndUpdate(window);
  300.     }
  301. }
  302.  
  303.  
  304.  
  305. /*****************************************************************************/
  306.  
  307.  
  308.  
  309. /* This is called when a mouse-down event occurs in the content of a window.
  310. ** Other applications might want to call FindControl, TEClick, etc., to
  311. ** further process the click.
  312. */
  313.  
  314. #pragma segment Main
  315. void    DoContentClick(WindowPtr window, EventRecord *event)
  316. {
  317.     Boolean            invertBoard;
  318.     short            fromRow, fromCol, toRow, toCol, i, myColor;
  319.     short            fromSq, toSq, promotion, piece, item;
  320.     short            numLegalMoves, part, twoPlayer;
  321.     OSErr            err;
  322.     long            moveAmount, ref;
  323.     Point            clickLoc, releaseLoc;
  324.     Rect            boardRect, squareRect;
  325.     RgnHandle        dragRgn;
  326.     FileRecHndl        frHndl;
  327.     MoveListHndl    legalMoves;
  328.     DialogPtr        promoteDialog;
  329.     short            itemType, ctlNum;
  330.     Handle            itemHndl;
  331.     Rect            itemRect;
  332.     ControlHandle    ctlHit;
  333.  
  334.     if (!IsAppWindow(window)) return;
  335.  
  336.     frHndl = (FileRecHndl)GetWRefCon(window);
  337.     SetPort(window);
  338.     SetOrigin((*frHndl)->doc.arrangeBoard * 4096, 0);
  339.  
  340.     twoPlayer = (*frHndl)->doc.twoPlayer;
  341.  
  342.     clickLoc = event->where;
  343.     GlobalToLocal(&clickLoc);
  344.  
  345.     if (CTEClick(event)) {
  346.         SetOrigin(0, 0);
  347.         return;
  348.     }
  349.         /* If TextEdit control handled the click, we are done. */
  350.  
  351.     if (part = FindControl(clickLoc, window, &ctlHit)) {
  352.         ctlNum = ref = GetCRefCon(ctlHit);
  353.         if ((ref) && (ref < 10)) {
  354.             if (TrackControl(ctlHit, clickLoc, nil)) {
  355.                 switch (ctlNum) {
  356.                     case 1:
  357.                         SendMssg(frHndl, kTextMssg);
  358.                         break;
  359.                     case 2:
  360.                     case 3:
  361.                         SetCtlValue(ctlHit, GetCtlValue(ctlHit) ^ 1);
  362.                         break;
  363.                     case 4:
  364.                     case 5:
  365.                         SetCtlValue(ctlHit, 1);
  366.                         SetCtlValue((*frHndl)->doc.wbStart[5 - ctlNum], 0);
  367.                         (*frHndl)->doc.startColor = ctlNum - 4;
  368.                         break;
  369.                     case 6:
  370.                         EndTheGame(frHndl, kWhiteResigns + (*frHndl)->doc.myColor);
  371.                         UpdateGameStatus(frHndl);
  372.                         if (twoPlayer) {
  373.                             SendGame(frHndl, kIsMove);
  374.                                 /* Show the dialog at the other end. */
  375.                             SendGame(frHndl, kResync);
  376.                                 /* Make sure that simultaneous hits on the
  377.                                 ** resign button are taken care of. */
  378.                         }
  379.                         break;
  380.                     case 7:
  381.                         i = ((*frHndl)->doc.drawBtnState ^ 0x02);
  382.                         if (!twoPlayer) i = 0x06;
  383.                         if (i >= 0x06) EndTheGame(frHndl, kDrawGame);
  384.                         DrawButtonTitle(frHndl, i);
  385.                         if (twoPlayer) {
  386.                             SendGame(frHndl, kIsMove);
  387.                                 /* Show the dialog at the other end. */
  388.                             SendGame(frHndl, kResync);
  389.                                 /* Make sure that simultaneous hits on the
  390.                                 ** draw button are taken care of. */
  391.                         }
  392.                         break;
  393.                     case 8:
  394.                         err = RecordSound(frHndl);
  395.                         if ((err) && (err != userCanceledErr)) Alert(rErrorAlert, nil);
  396.                         break;
  397.                     case 9:
  398.                         SendMssg(frHndl, kSoundMssg);
  399.                         break;
  400.                 }
  401.             }
  402.         }
  403.         SetOrigin(0, 0);
  404.  
  405.         if (ctlHit == (*frHndl)->doc.gameSlider)
  406.             TrackControl(ctlHit, clickLoc, nil);
  407.  
  408.         return;
  409.     }
  410.  
  411.     if ((*frHndl)->fileState.readOnly) {
  412.         SetOrigin(0, 0);
  413.         return;
  414.     }                    /* Don't allow changes if read-only. */
  415.  
  416.     if ((*frHndl)->doc.arrangeBoard) {
  417.         DoArrangeBoard(frHndl, clickLoc);
  418.         return;
  419.     }
  420.  
  421.     SetOrigin(0, 0);
  422.  
  423.     invertBoard = (*frHndl)->doc.invertBoard;
  424.  
  425.     boardRect = BoardRect();
  426.     if (!PtInRect(clickLoc, &boardRect)) return;
  427.  
  428.     fromRow = (clickLoc.v - kBoardVOffset) / kBoardSqSize;
  429.     fromCol = (clickLoc.h - kBoardHOffset) / kBoardSqSize;
  430.  
  431.     squareRect.top    = kBoardVOffset + fromRow * kBoardSqSize;
  432.     squareRect.left   = kBoardHOffset + fromCol * kBoardSqSize;
  433.     squareRect.bottom = squareRect.top  + kBoardSqSize + 2;
  434.     squareRect.right  = squareRect.left + kBoardSqSize + 2;
  435.  
  436.     if (invertBoard) {
  437.         fromRow = 7 - fromRow;
  438.         fromCol = 7 - fromCol;
  439.     }
  440.     fromSq  = START_IBNDS + 10 * fromRow + fromCol;
  441.  
  442.     if (GameStatus(frHndl) != kGameContinues) return;
  443.         /* Game over, so no moves. */
  444.  
  445.     if ((*frHndl)->doc.resync != kIsMove) return;
  446.         /* Don't allow moves until we are resynced. */
  447.  
  448.     numLegalMoves = (*frHndl)->doc.numLegalMoves;
  449.     legalMoves    = (*frHndl)->doc.legalMoves;
  450.  
  451.     for (i = 0; i < numLegalMoves; ++i)
  452.         if ((**legalMoves)[i].moveFrom == fromSq) break;
  453.  
  454.     if (i == numLegalMoves) return;
  455.         /* Clicked on a empty square or on a piece that can't move. */
  456.  
  457.     myColor = (*frHndl)->doc.myColor;
  458.     if (twoPlayer)
  459.         if (WhosMove(frHndl) != myColor) return;
  460.             /* It's the other player's turn. */
  461.  
  462.     if ((myColor == WHITE) && ((*frHndl)->doc.compMovesWhite)) return;
  463.     if ((myColor == BLACK) && ((*frHndl)->doc.compMovesBlack)) return;
  464.         /* Computer is moving this color, so ignore click. */
  465.  
  466.     dragRgn = NewRgn();
  467.     RectRgn(dragRgn, &squareRect);
  468.     moveAmount = DragGrayRgn(dragRgn, clickLoc, &boardRect, &boardRect,
  469.                              noConstraint, nil);
  470.     DisposeRgn(dragRgn);
  471.  
  472.     if (moveAmount == 0x80008000L) return;
  473.  
  474.     releaseLoc.h = clickLoc.h + (moveAmount & 0xFFFF);
  475.     moveAmount   = moveAmount >> 16;
  476.     releaseLoc.v = clickLoc.v + (moveAmount & 0xFFFF);
  477.  
  478.     toRow = (releaseLoc.v - kBoardVOffset) / kBoardSqSize;
  479.     toCol = (releaseLoc.h - kBoardHOffset) / kBoardSqSize;
  480.     if (invertBoard) {
  481.         toRow = 7 - toRow;
  482.         toCol = 7 - toCol;
  483.     }
  484.     toSq  = START_IBNDS + 10 * toRow + toCol;
  485.  
  486.     for (i = 0; i < numLegalMoves; ++i)
  487.         if (
  488.             ((**legalMoves)[i].moveFrom == fromSq) &&
  489.             ((**legalMoves)[i].moveTo   == toSq)
  490.         ) break;
  491.  
  492.     if (i == numLegalMoves) return;        /* Tried an illegal move. */
  493.  
  494.     promotion = QUEEN;        /* If there is a promotion, assume queen. */
  495.  
  496.     if ((toRow == 0) || (toRow == 7)) {        /* Possible pawn promotion... */
  497.  
  498.         piece = (*frHndl)->doc.theBoard[fromSq];
  499.         if (piece < 0) piece = -piece;
  500.  
  501.         if (piece == PAWN) {                /* It is a pawn promotion... */
  502.             promoteDialog = GetCenteredDialog(rPawnPromotion, nil, nil, (WindowPtr)-1L);
  503.  
  504.             if (promoteDialog) {
  505.                 OutlineDialogItem(promoteDialog, 1);
  506.                 DoSetCursor(&qd.arrow);
  507.  
  508.                 for (item = QUEEN;;) {
  509.                     if (promotion != item) {
  510.                         GetDItem(promoteDialog, promotion + 1, &itemType, &itemHndl, &itemRect);
  511.                         SetCtlValue((ControlHandle)itemHndl, false);
  512.                     }
  513.  
  514.                     GetDItem(promoteDialog, item + 1, &itemType, &itemHndl, &itemRect);
  515.                     SetCtlValue((ControlHandle)itemHndl, true);
  516.                     promotion = item;
  517.  
  518.                     ModalDialog((ModalFilterProcPtr)keyEquivFilter, &item);
  519.                     if (item == 1) break;
  520.                     --item;
  521.                 }
  522.                 DisposDialog(promoteDialog);
  523.             }
  524.             SetPort(window);
  525.         }
  526.     }
  527.  
  528.     UpdateTime(frHndl, true);
  529.     MakeMove(frHndl, fromSq, toSq, promotion, true);
  530.     ImageDocument(frHndl, true);
  531.     DrawTime(frHndl);
  532.     AdjustGameSlider(frHndl);
  533.     DrawButtonTitle(frHndl, (*frHndl)->doc.twoPlayer);
  534.     UpdateGameStatus(frHndl);
  535.  
  536.     if (twoPlayer) SendGame(frHndl, kIsMove);
  537.     AlertIfGameOver(frHndl);
  538. }
  539.  
  540.  
  541.  
  542. /*****************************************************************************/
  543.  
  544.  
  545.  
  546. #pragma segment Main
  547. short    AlertIfGameOver(FileRecHndl frHndl)
  548. {
  549.     short    status;
  550.     Str255    gameStatMssg;
  551.  
  552.     if ((status = GameStatus(frHndl)) != kGameContinues) {
  553.         UpdateGameStatus(frHndl);
  554.         GetIndString(gameStatMssg, rGameStat, status);
  555.         ParamText(gameStatMssg, nil, nil, nil);
  556.         DoSetCursor(&qd.arrow);
  557.         CenteredAlert(rGameStat, nil);
  558.     }
  559.     return(status);
  560. }
  561.  
  562.  
  563.  
  564.